10378. Непредставимые
Задано натуральное число n.
Сколько чисел от 1 до n (включительно) непредставимы
в виде ab, где a и b – натуральные числа, не менее 2?
Вход. Одно натуральное
число n (1 ≤ n ≤ 1010).
Выход.
Выведите количество непредставимых чисел.
Пример входа 1 |
Пример выхода 1 |
8 |
6 |
|
|
Пример входа 2 |
Пример выхода 2 |
100000 |
99634 |
структуры
данных - set
Количество непредставимых
чисел равно
n – количество чисел, представимых в виде ab
Найдем все
числа, представимые в виде ab, где a
> 1, b > 1, ab ≤ n. Таких
чисел немного, так что их всех можно сгенерировать и сохранить в контейнер.
Степени будут повторяться, например 212, 46 и 163.
Повторы чисел следует удалять, поэтому в качестве контейнера выберем множество set.
Будем генерировать
степени ab, где a = 2, 3, 4, …,
. Для каждого значения a
перебираем b = 2, 3, 4, … пока степень не больше n. Например:
·
степени двойки 22, 23,
24, … ≤
n;
·
степени тройки 32, 33,
34, … ≤
n;
·
степени четверки 42, 43,
44, … ≤
n;
Пример
На промежутке [1; 8] имеются два
числа представимые в виде степеней: 22 = 4 и 23 = 8.
Таким образом непредставимых будет 8 – 2 = 6 чисел.
Пусть n = 50. Тогда
будут сгенерированы следующие степени:
·
22 = 4, 23 = 8, 24
= 16, 25 = 32 (26 = 64 > 50);
·
32 = 9, 33 = 27 (34 = 81 > 50);
·
42 = 16 (43 = 64 > 50);
·
52 = 25 (53 = 125 > 50);
·
62 = 36 (63 = 216 > 50);
·
72 = 49 (73 = 343 > 50);
Заметим, что 24
= 16 и 42 = 16, однако во
множестве дубли удалятся. Для n = 50 множество s будет
иметь вид: {4, 8, 9, 16,
25, 27, 32, 36, 49}. Количество непредставимых чисел на промежутке [1; 50] равно 50 – s.size() = 50 –
9 = 41.
Реализация алгоритма
Объявим множество s.
#define ll long long
set<ll> s;
Читаем входное значение n.
scanf("%lld", &n);
Перебираем основание степени a.
for (a = 2;
a * a <= n; a++)
{
Инициализируем x = a2. Далее в переменной x перебираем степени числа a: a3, a4, … . Заносим сгенерированные степени
во множество s.
ll x = a * a;
while (x <= n)
{
s.insert(x);
x *= a;
}
}
Значение
s.size() содержит количество чисел,
представимых в виде ab. Выводим ответ, равный n – s.size().
printf("%lld\n", n -
s.size());
Java реализация
import java.util.*;
class Main
{
public static void
main(String[] args)
{
Scanner con = new Scanner(System.in);
TreeSet<Long> s = new TreeSet<Long>();
long n = con.nextLong();
for (long a = 2; a * a <= n; a++)
{
long x = a * a;
while (x <= n)
{
s.add(x);
x *= a;
}
}
System.out.print(n - s.size());
con.close();
}
}